//
//package cn.intotw.rdcj.core.config.mybatis;
//
//import java.lang.reflect.Field;
//import java.sql.DatabaseMetaData;
//import java.util.ArrayList;
//import java.util.Iterator;
//import java.util.List;
//import java.util.Map;
//import java.util.Properties;
//
//import cn.intotw.rdcj.core.config.mybatis.dialect.Dialect;
//import cn.intotw.rdcj.core.config.mybatis.entity.PageList;
//import cn.intotw.rdcj.core.config.mybatis.entity.PageQuery;
//import org.apache.ibatis.executor.Executor;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.mapping.ParameterMapping;
//import org.apache.ibatis.mapping.ResultMap;
//import org.apache.ibatis.mapping.ResultMapping;
//import org.apache.ibatis.mapping.SqlSource;
//import org.apache.ibatis.mapping.ResultMap.Builder;
//import org.apache.ibatis.plugin.Interceptor;
//import org.apache.ibatis.plugin.Intercepts;
//import org.apache.ibatis.plugin.Invocation;
//import org.apache.ibatis.plugin.Plugin;
//import org.apache.ibatis.plugin.Signature;
//import org.apache.ibatis.session.Configuration;
//import org.apache.ibatis.session.ResultHandler;
//import org.apache.ibatis.session.RowBounds;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//@Intercepts({@Signature(
//    type = Executor.class,
//    method = "query",
//    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
//)})
//public class PageInterceptor implements Interceptor {
//    private static final Logger log = LoggerFactory.getLogger(PageInterceptor.class);
//    private static final List<ResultMapping> EMPTY_RESULT_MAPPINGS = new ArrayList(0);
//    static int MAPPED_STATEMENT_INDEX = 0;
//    static int PARAMETER_INDEX = 1;
//    static int ROW_BOUNDS_INDEX = 2;
//    static int RESULT_HANDLER_INDEX = 3;
//    private Field additionalParametersField;
//
//    public PageInterceptor() {
//        try {
//            this.additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
//            this.additionalParametersField.setAccessible(true);
//        } catch (NoSuchFieldException var2) {
//            throw new RuntimeException(var2);
//        }
//    }
//
//    public Object intercept(Invocation invocation) throws Throwable {
//        Executor executor = (Executor)invocation.getTarget();
//        Object[] queryArgs = invocation.getArgs();
//        MappedStatement ms = (MappedStatement)queryArgs[MAPPED_STATEMENT_INDEX];
//        Object parameter = queryArgs[PARAMETER_INDEX];
//        RowBounds rowBounds = (RowBounds)queryArgs[ROW_BOUNDS_INDEX];
//        ResultHandler resultHandler = (ResultHandler)queryArgs[RESULT_HANDLER_INDEX];
//        if (parameter != null && parameter instanceof PageQuery) {
//            DatabaseMetaData databaseMetaData = executor.getTransaction().getConnection().getMetaData();
//            Dialect dialect = Dialect.createDialect(databaseMetaData);
//            PageList pageList = new PageList();
//            boolean paging = false;
//            PageQuery pageQuery = (PageQuery)parameter;
//            if (pageQuery.getPageNo() != null && pageQuery.getPageNo() > 0 && pageQuery.getPageSize() != null && pageQuery.getPageSize() > 0) {
//                paging = true;
//                BoundSql boundSql = ms.getBoundSql(parameter);
//                queryArgs[0] = this.newPageMappedStatement(ms, boundSql, dialect, pageQuery.getPageNo(), pageQuery.getPageSize());
//                List rows = (List)invocation.proceed();
//                pageList.addAll(rows);
//                if (pageQuery.getCountTotal()) {
//                    Object countResultList = executor.query(this.newCountMappedStatement(ms, boundSql, dialect), parameter, rowBounds, resultHandler);
//                    int count = (Integer)((List)countResultList).get(0);
//                    pageList.setTotalCount(count);
//                } else {
//                    pageList.setTotalCount(pageList.size() == pageQuery.getPageSize() ? pageQuery.getPageNo() * pageQuery.getPageSize() + 1 : pageQuery.getPageNo() * (pageQuery.getPageSize() - 1) + pageList.size());
//                }
//
//                pageList.setPageNo(pageQuery.getPageNo());
//                pageList.setPageSize(pageQuery.getPageSize());
//                pageList.setTotalPage((int)Math.ceil((double)pageList.getTotalCount() / (double)pageList.getPageSize()));
//            }
//
//            if (!paging) {
//                List rows = (List)invocation.proceed();
//                pageList.setTotalPage(1);
//                pageList.setTotalCount(rows == null ? 0 : rows.size());
//                pageList.setPageNo(1);
//                pageList.setPageSize(pageList.getTotalCount());
//                pageList.addAll(rows);
//            }
//
//            return pageList;
//        } else {
//            return invocation.proceed();
//        }
//    }
//
//    public Object plugin(Object target) {
//        return target instanceof Executor ? Plugin.wrap(target, this) : target;
//    }
//
//    public void setProperties(Properties properties) {
//    }
//
//    public MappedStatement newPageMappedStatement(MappedStatement ms, BoundSql boundSql, Dialect dialect, int pageNo, int pageSize) throws IllegalAccessException {
//        String pageSql = dialect.getPageSql(boundSql.getSql(), pageNo, pageSize);
//        Map<String, Object> additionalParameters = (Map)this.additionalParametersField.get(boundSql);
//        log.debug("Total page SQL [{}] ", pageSql);
//        log.debug("Total page Parameters: {} ", boundSql.getParameterObject());
//        log.debug("Total page Additional Parameters: {} ", additionalParameters);
//        SqlSource sqlSource = new PageInterceptor.AdditionalStaticSqlSource(ms.getConfiguration(), pageSql, boundSql.getParameterMappings(), additionalParameters);
//        return this.newMappedStatement(ms, sqlSource, ms.getResultMaps());
//    }
//
//    public MappedStatement newCountMappedStatement(MappedStatement ms, BoundSql boundSql, Dialect dialect) throws IllegalAccessException {
//        String countSql = dialect.getCountSql(boundSql.getSql());
//        Map<String, Object> additionalParameters = (Map)this.additionalParametersField.get(boundSql);
//        log.debug("Total count SQL [{}] ", countSql);
//        log.debug("Total count Parameters: {} ", boundSql.getParameterObject());
//        log.debug("Total count Additional Parameters: {} ", additionalParameters);
//        SqlSource sqlSource = new PageInterceptor.AdditionalStaticSqlSource(ms.getConfiguration(), countSql, boundSql.getParameterMappings(), additionalParameters);
//        List<ResultMap> resultMaps = new ArrayList();
//        ResultMap resultMap = (new Builder(ms.getConfiguration(), ms.getId(), Integer.class, EMPTY_RESULT_MAPPINGS)).build();
//        resultMaps.add(resultMap);
//        return this.newMappedStatement(ms, sqlSource, resultMaps);
//    }
//
//    private MappedStatement newMappedStatement(MappedStatement ms, SqlSource sqlSource, List<ResultMap> resultMaps) throws IllegalAccessException {
//        org.apache.ibatis.mapping.MappedStatement.Builder builder = new org.apache.ibatis.mapping.MappedStatement.Builder(ms.getConfiguration(), ms.getId(), sqlSource, ms.getSqlCommandType());
//        builder.resource(ms.getResource());
//        builder.fetchSize(ms.getFetchSize());
//        builder.statementType(ms.getStatementType());
//        builder.keyGenerator(ms.getKeyGenerator());
//        if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
//            StringBuilder keyProperties = new StringBuilder();
//            String[] var6 = ms.getKeyProperties();
//            int var7 = var6.length;
//
//            for(int var8 = 0; var8 < var7; ++var8) {
//                String keyProperty = var6[var8];
//                keyProperties.append(keyProperty).append(",");
//            }
//
//            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
//            builder.keyProperty(keyProperties.toString());
//        }
//
//        builder.timeout(ms.getTimeout());
//        builder.parameterMap(ms.getParameterMap());
//        builder.resultMaps(resultMaps);
//        builder.resultSetType(ms.getResultSetType());
//        builder.cache(ms.getCache());
//        builder.flushCacheRequired(ms.isFlushCacheRequired());
//        builder.useCache(ms.isUseCache());
//        return builder.build();
//    }
//
//    public static class AdditionalStaticSqlSource implements SqlSource {
//        private String sql;
//        private List<ParameterMapping> parameterMappings;
//        private Configuration configuration;
//        private Map<String, Object> additionalParameters;
//
//        public AdditionalStaticSqlSource(Configuration configuration, String sql) {
//            this(configuration, sql, (List)null, (Map)null);
//        }
//
//        public AdditionalStaticSqlSource(Configuration configuration, String sql, List<ParameterMapping> parameterMappings) {
//            this(configuration, sql, parameterMappings, (Map)null);
//        }
//
//        public AdditionalStaticSqlSource(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Map<String, Object> additionalParameters) {
//            this.sql = sql;
//            this.parameterMappings = parameterMappings;
//            this.configuration = configuration;
//            this.additionalParameters = additionalParameters;
//        }
//
//        public BoundSql getBoundSql(Object parameterObject) {
//            BoundSql boundSql = new BoundSql(this.configuration, this.sql, this.parameterMappings, parameterObject);
//            if (this.additionalParameters != null) {
//                Iterator var3 = this.additionalParameters.keySet().iterator();
//
//                while(var3.hasNext()) {
//                    String key = (String)var3.next();
//                    boundSql.setAdditionalParameter(key, this.additionalParameters.get(key));
//                }
//            }
//
//            return boundSql;
//        }
//    }
//}
